package cn.tedu.charging.device.service;

import cn.tedu.charging.common.pojo.po.ChargingGunInfoPO;
import cn.tedu.charging.common.pojo.po.ChargingStationPO;
import cn.tedu.charging.common.pojo.query.NearStationsQuery;
import cn.tedu.charging.common.pojo.vo.GunInfoVO;
import cn.tedu.charging.common.pojo.vo.StationDetailVO;
import cn.tedu.charging.common.pojo.vo.StationInfoVO;
import cn.tedu.charging.device.repository.DeviceRepository;
import com.alibaba.nacos.common.utils.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.redis.domain.geo.GeoLocation;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService{
    @Autowired
    private DeviceRepository deviceRepository;
    private static Map<Integer,List<Integer>> gunStatusMap;
    static{
        //枪状态流转数据规则全部初始化给这个map
        gunStatusMap=new HashMap<>();
        gunStatusMap.put(1,CollectionUtils.list(2,3));
        //能转成1的list{2,3}
        gunStatusMap.put(2,CollectionUtils.list(1));
        //能转成2的list{1}
        gunStatusMap.put(3,CollectionUtils.list(1,2));
        //能转成3的list{1,2}
        gunStatusMap.put(4,CollectionUtils.list(1,3));
        //能转成4的list{1,3}
    }
    @Override
    public List<StationInfoVO> nearStations(NearStationsQuery query) {
        //stationInfoVo属性 除了stationName以外 全部都来自于geo;
        //1.从仓储层 读取能够命中的 geo元素集合 List<GeoResult> 包含元素 distance point
        List<GeoResult> geoResults=deviceRepository.nearStations(query);
        //2.将geoResult类型每个元素 封装转化vo geoResult-->stationVos;
        //第一种方案 直接判断geoResults非空 循环遍历转化
        //第二种方案 判断非空 映射转化 list stream流的api map
        List<StationInfoVO> vos=null;
        //判断geoResult非空
        if(geoResults!=null&&geoResults.size()>0){
            log.debug("查询到了geoResults");
            vos=geoResults.stream().map(result->{
                //距离初始化的值 没有处理小数点位数
                Double distance=result.getDistance().getValue();
                distance=new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP).doubleValue();
                //lng lat
                GeoLocation location=(GeoLocation)result.getContent();
                Double lng=location.getPoint().getX();
                Double lat=location.getPoint().getY();
                //stationId
                Integer stationId=(Integer)location.getName();
                //stationName 需要让仓储层查询
                String stationName=deviceRepository.getStationName(stationId);
                StationInfoVO vo=new StationInfoVO();
                vo.setStationId(stationId);
                vo.setDistance(distance);//km单位 取2位小数点 四舍五入
                vo.setStationLat(new BigDecimal(lat));
                vo.setStationLng(new BigDecimal(lng));
                vo.setStationName(stationName);
                return vo;
            }).collect(Collectors.toList());
        }else{
            log.debug("没有查询到geoResults");
        }
        return vos;
    }

    @Override
    public StationDetailVO detailStation(Integer stationId) {
        //1.查询站场详情 无论从数据库返回查询结果 还是缓存都是使用po
        ChargingStationPO station=deviceRepository.getStationById(stationId);
        //2.查询站场下所有枪列表
        List<ChargingGunInfoPO> guns=deviceRepository.getGunListByStationId(stationId);
        //3.组织封装返回的vo
        StationDetailVO vo=new StationDetailVO();
        vo.setStationName(station.getStationName());
        vo.setAddress(station.getAddress());
        //当前站场下的枪列表 需要用guns转化
        List<GunInfoVO> gunVos=null;
        if (guns!=null&&guns.size()>0){
            gunVos=guns.stream().map(gunPo->{
                //把po 转vo
                GunInfoVO gunVo=new GunInfoVO();
                BeanUtils.copyProperties(gunPo,gunVo);
                return gunVo;
            }).collect(Collectors.toList());
        }
        vo.setGunInfoPOList(gunVos);
        return vo;
    }

    /**
     * key表示目标状态
     * value表示可以修改成目标状态的来源
     */
    @Override
    public Boolean updateGunStatus(Integer gunId, Integer status) {
        //update set status=1 where gunId=? and status in (2,3)
        return deviceRepository.updateGunStatus(gunId,status,gunStatusMap.get(status));
    }
}
